/*
 * FaceTextPainter.cpp
 *
 *  Created on: 2018年8月13日
 *      Author: zhengboyuan
 */

#include "FaceTextPainter.h"
#include "BasicMacro.h"

#include "CLog.h"
#include "TStringUtil.h"
#include <time.h>
#include "DateTime.h"
#include <assert.h>


bool FaceTextPainter::SHOW_PTS = false;

FaceTextPainter::FaceTextPainter():
	m_pts(),
	m_duration(),
	m_expiredPts()
{
	m_textFont.update(0, 36);
}

FaceTextPainter::~FaceTextPainter()
{
}

void FaceTextPainter::setText(const std::string& text, int64_t pts, int duration, int flags)
{
	if (text.empty())
	{
		clear();
		return;
	}

	//if (flags == av::MEDIA_SUBTITLE_FACE)
	{
		Json::Value value;
		Json::Reader reader;
		if (reader.parse(text, value))
		{
			m_faceText.parse(value);
		}
		else
		{
			m_faceText.clear();
		}

		m_pts = pts;
		m_duration = duration;
		m_expiredPts = m_pts + m_duration;
	}
	
}

std::string toClock(int64_t pts)
{
	std::string text;
	int64_t ms = pts / 1000;
	int64_t seconds = ms / 1000;
	int64_t minutes = (seconds / 60);
	text = comn::StringUtil::format("%d:%d.%d", minutes % 60, seconds % 60, ms);
	return text;
}


void FaceTextPainter::draw(HWND hwnd, HDC hdc, const RECT& rcWin, const RECT& rcDest, int width, int height, int64_t pts)
{
	if (m_faceText.empty())
	{
		return;
	}

	assert(m_pts == m_faceText.m_frameId);

	SetBkMode(hdc, TRANSPARENT);

	HPEN hPen = m_pen.update(PS_SOLID, m_faceText.m_lineSize, m_faceText.m_lineColor);
	HGDIOBJ hOldPen = SelectObject(hdc, hPen);

	HFONT hFont = m_font.update(m_faceText.m_fontType, m_faceText.m_fontSize);
	HGDIOBJ hOldFont = SelectObject(hdc, hFont);
	SetTextColor(hdc, m_faceText.m_fontColor);

	for (size_t i = 0; i < m_faceText.m_faces.size(); i++)
	{
		const FaceText::Face& face = m_faceText.m_faces[i];
		FaceText::Face outFace = mapCoord(face, rcWin, rcDest, width, height);

		//CLog::debug("face rect. x1: %f, y1: %f, x2:%f, y2:%f\n", face.left, face.top, face.right, face.bottom);

		RECT rc = { (int)outFace.left, (int)outFace.top, (int)outFace.right, (int)outFace.bottom};
		drawRect(hdc, rc);

		int x = (int)(outFace.x);
		int y = (int)(outFace.y) - m_faceText.m_fontSize;

		TextOutA(hdc, x, y, face.text.c_str(), face.text.size());
		//DrawTextA(hdc, face.text.c_str(), face.text.size(), &rc, DT_LEFT);
	}

	if (SHOW_PTS)
	{
		SelectObject(hdc, m_textFont.get());

		std::string clock = toClock(pts);
		std::string text = comn::StringUtil::format("video: %lld, %s", pts /1000, clock.c_str());
		TextOutA(hdc, 20, 100, text.c_str(), text.size());

		clock = toClock(m_faceText.m_frameId);
		int offset = (int)((pts - m_faceText.m_frameId) / 1000);
		
		text = comn::StringUtil::format("faces: %lld, %s, off: %d, count: %d", m_faceText.m_frameId / 1000, clock.c_str(), offset, m_faceText.m_faces.size());
		TextOutA(hdc, 20, 160, text.c_str(), text.size());
	}

	SelectObject(hdc, hOldFont);
	SelectObject(hdc, hOldPen);
}

void FaceTextPainter::drawRect(HDC hdc, const RECT& rc)
{
	POINT points[] = 
	{
		{rc.left, rc.top},
		{ rc.right, rc.top },
		{ rc.right, rc.bottom },
		{ rc.left, rc.bottom },
		{ rc.left, rc.top }
	};
	Polyline(hdc, points, ARRAY_SIZE(points));
}

FaceText::Face FaceTextPainter::mapCoord(const FaceText::Face& face, const RECT& rcWin, const RECT& rcDest, int width, int height)
{
	FaceText::Face outFace = face;

	int destWidth = rcDest.right - rcDest.left;
	int destHeight = rcDest.bottom - rcDest.top;

	int xOffset = rcDest.left - rcWin.left;
	int yOffset = rcDest.top - rcWin.top;

	outFace.left = face.left * destWidth / width + xOffset;
	outFace.right = face.right * destWidth / width + xOffset;
	outFace.top = face.top * destHeight / height + yOffset;
	outFace.bottom = face.bottom * destHeight / height + yOffset;

	outFace.x = face.x * destWidth / width + xOffset;;
	outFace.y = face.y * destHeight / height + yOffset;

	return outFace;
}

bool FaceTextPainter::isEmpty()
{
	return m_faceText.empty();
}

int64_t FaceTextPainter::getPts()
{
	return m_pts;
}

int64_t FaceTextPainter::getExpiredPts()
{
	return m_expiredPts;
}

void FaceTextPainter::clear()
{
	m_pts = 0;
	m_duration = 0;
	m_expiredPts = 0;

	m_faceText.clear();
}